package com.learn.excel.core.util.shell;

import lombok.experimental.UtilityClass;

import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * @Classname ShellUtils
 * @Description TODO
 * @Author zxy
 */
@UtilityClass
public class ShellUtils {

	/**
	 * <p>
	 * 执行命令
	 * @author zxy
	 **/
	public RCmd exec(String commond) {
		Process process = null;
		// 10秒
		long timeout = 10 * 1000;
		CommandStreamGobbler errorGobbler = null;
		CommandStreamGobbler outGobbler = null;
		try {
			process = Runtime.getRuntime().exec(commond);
			errorGobbler = new CommandStreamGobbler(process.getErrorStream(), commond);
			outGobbler = new CommandStreamGobbler(process.getInputStream(), commond);
			errorGobbler.start();
			// 必须先等待错误输出ready建立标准输出
			while (!errorGobbler.isReady()) {
				Thread.sleep(10);
			}
			outGobbler.start();
			while (!outGobbler.isReady()) {
				Thread.sleep(10);
			}
			CommandWaitForThread commandThread = new CommandWaitForThread(process);
			commandThread.start();
			long commondTime = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
			long nowTime = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
			boolean timeoutFlag = false;
			while (!commondIsFinsih(commandThread, errorGobbler, outGobbler)) {
				if (nowTime - commondTime > timeout) {
					timeoutFlag = true;
					break;
				}
				else {
					Thread.sleep(100);
					nowTime = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
				}
			}
			if (timeoutFlag) {
				errorGobbler.setTimeout(1);
				outGobbler.setTimeout(1);
				System.out.println("正在执行的命令：" + commond + "超时！");
			}
			else {
				errorGobbler.setTimeout(2);
				outGobbler.setTimeout(2);
			}
			while (true) {
				if (errorGobbler.isReadFinish() && outGobbler.isReadFinish()) {
					break;
				}
				Thread.sleep(10);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			if (process != null) {
				process.destroy();
			}
		}
		RCmd rCmd = new RCmd();

		if (null != errorGobbler && errorGobbler.getInfoList().size() > 0) {
			rCmd.setSuccess(false);
			StringBuilder sb = new StringBuilder();
			for (String tmp : errorGobbler.getInfoList()) {
				sb.append(tmp).append("\n");
			}
			rCmd.setMessage(sb.toString());
		}

		if (null != outGobbler  && outGobbler.getInfoList().size() > 0) {
			rCmd.setSuccess(true);
			StringBuilder sb = new StringBuilder();
			for (String tmp : outGobbler.getInfoList()) {
				sb.append(tmp).append("\n");
			}
			rCmd.setMessage(sb.toString());
		}

		return rCmd;
	}

	private boolean commondIsFinsih(CommandWaitForThread commandThread, CommandStreamGobbler errorGobbler,
			CommandStreamGobbler outGobbler) {
		if (commandThread != null) {
			return commandThread.isFinish();
		}
		else {
			return (errorGobbler.isReadFinish() && outGobbler.isReadFinish());
		}
	}

}
